#include "hcstrstream.h"
#include <string.h>
#include <memory.h>
#include <gc.h>

const int STREAM_CAPACITY_DEF = 80;
const int STREAM_CAPACITY_INC = 40;

hcstrstream* hcstrstream_create() {
    hcstrstream* s = (hcstrstream*) GC_MALLOC(sizeof(hcstrstream));
    s->length = 0;
    s->position = 0;
    s->capacity = STREAM_CAPACITY_DEF;
    s->data = (char*) GC_MALLOC(sizeof(char) * s->capacity);
    memset((void*) s->data, 0, (size_t) s->capacity);
    return s;
}

void hcstrstream_write(hcstrstream* s, hcstring* text) {
    hcstrstream_write_char(s, text->text, text->length);
}

void hcstrstream_write_char(hcstrstream* s, char* text, int length) {
    int min_cap_req = 0;
    if(0 >= length) {
	length = strlen(text);
    }
    min_cap_req = s->position + length + 1;
    if(s->capacity <= min_cap_req) {
	char* buffer = (char*) GC_MALLOC(sizeof(char) * s->length);
	int index = 0;
	for(index = 0; index < s->length; index++) {
	    buffer[index] = s->data[index];
	}
	while(s->capacity < min_cap_req) {
	    s->capacity = s->capacity + STREAM_CAPACITY_INC;
	}
	GC_FREE(s->data);
	s->data = (char*) GC_MALLOC(sizeof(char) * s->capacity);
	memset((void*) s->data, 0, (size_t) s->capacity);
	for(index = 0; index < s->length; index++) {
	    s->data[index] = buffer[index];
	}
	GC_FREE(buffer);
    }
    {
	int index = 0;
	for(index = s->position; index < (s->position + length); index++) {
	    s->data[index] = text[index - s->position];
	}
	s->position = index;
	if(s->length < s->position) {
	    s->length = s->position;
	}
    }
}

hcstring* hcstrstream_read(hcstrstream* s) {
    return hcstring_create(s->data);
}